home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / boot / CommandLoop.c < prev    next >
C/C++ Source or Header  |  1991-01-17  |  28KB  |  1,131 lines

  1. /* begincopyright
  2.   Copyright (c) 1988 Xerox Corporation. All rights reserved.
  3.   Use and copying of this software and preparation of derivative works based
  4.   upon this software are permitted. Any distribution of this software or
  5.   derivative works must comply with all applicable United States export
  6.   control laws. This software is made available AS IS, and Xerox Corporation
  7.   makes no warranty about the software, its performance or its conformity to
  8.   any specification. Any person obtaining a copy of this software is requested
  9.   to send their name and post office or electronic mail address to
  10.   PCRCoordinator.pa@xerox.com, or to:
  11.     PCR Coordinator
  12.     Xerox PARC
  13.     3333 Coyote Hill Rd.
  14.     Palo Alto, CA 94304
  15.   endcopyright */
  16.  
  17. /*
  18.  * CommandLoop.c
  19.  *
  20.  * Demers, January 17, 1991 4:59:36 pm PST
  21.  * 
  22.  */
  23.  
  24. #include <xr/Threads.h>
  25. #include <xr/ThreadsBackdoor.h>
  26. #include <xr/UIO.h>
  27. #include <xr/ThreadsMsg.h>
  28. #include <xr/CommandLine.h>
  29. #include <xr/CommandLoop.h>
  30. #include <xr/IncrementalLoad.h>
  31.  
  32. #include <string.h>
  33.  
  34. /*DEBUG*/
  35. #include <xr/CommandLinePrivate.h>
  36.  
  37. XR_CLHandle XR_globalCLHandle = NIL;
  38.  
  39. XR_CLProcsHandle XR_globalCLProcsHandle = NIL;
  40.  
  41. #ifdef UNDEFINED
  42.  
  43. int
  44. XR_UnlinkSymtabFiles()
  45. {
  46.     int ans1, ans2;
  47.     char name[1024];
  48.  
  49.     XR_ILGetInfoFileName(name);
  50.     ans1 = unlink(name);
  51.     (void)strcat(name, ".dbx");  /* the same name used in generated XrDBX */
  52.     ans2 = unlink(name);
  53.     return( (ans1 || ans2) ? -1 : 0 );
  54. }
  55.  
  56. #endif
  57.  
  58.  
  59. /* ??? is the following still needed? ??? */
  60. XR_Pointer
  61. XR_ExtensionFree()
  62. {
  63. }
  64.  
  65.  
  66.  
  67. /*
  68.  * recursive command processing
  69.  */
  70.  
  71.  
  72. /* top-level call environment */
  73.  
  74. static XR_CLCallEnv XR_topLevelCLCallEnv = NIL;
  75.  
  76. XR_CLCallEnv
  77. XR_GetTopLevelCLCallEnv()
  78. {
  79.     return XR_topLevelCLCallEnv;
  80. }
  81.  
  82.  
  83. XR_CLCallEnv
  84. XR_SetTopLevelCLCallEnv(clceNew)
  85.     XR_CLCallEnv clceNew;
  86. {
  87.     XR_CLCallEnv clceOld = XR_topLevelCLCallEnv;
  88.     XR_topLevelCLCallEnv = clceNew;
  89.     return clceOld;
  90. }
  91.  
  92.  
  93.  
  94. /* top-level message sink */
  95.  
  96.  
  97. static void
  98. XR_StdOutCLMsgSink(buf, nBytes, self)
  99.     char *buf;
  100.     int nBytes;
  101.     XR_MesaProc self;
  102. {
  103.     (void)XR_Write(XR_MSG_STDOUT, buf, nBytes);
  104. }
  105.  
  106. static struct XR_MesaProcRep XR_stdOutCLMsgSinkRep = {
  107.     (XR_UntypedProc)(XR_StdOutCLMsgSink),
  108.     (XR_Pointer)(NIL)
  109. };
  110.  
  111. XR_MesaProc XR_stdOutCLMsgSink = &XR_stdOutCLMsgSinkRep;
  112.  
  113.  
  114.  
  115. /* top-level jmpbuf -- longjmp here returns from CLProc */
  116.  
  117.  
  118. XR_JmpBuf
  119. XR_GetTopLevelJumpBuf()
  120. {
  121.     XR_CLCallEnv clce = XR_topLevelCLCallEnv;
  122.     return ((clce == NIL) ? NIL : &(clce->clce_jmpBuf));
  123. }
  124.  
  125.  
  126. /* top-level CL error handler -- if non-nil, called w/result on error */
  127.  
  128. void
  129. XR_StoreTopLevelCLErrorHandler(mp)
  130.     XR_MesaProc mp;
  131. {
  132.     XR_CLCallEnv clce = XR_topLevelCLCallEnv;
  133.     if( clce != NIL ) clce->clce_handlerProc = mp;
  134. }
  135.  
  136.  
  137.  
  138. static int
  139. XR_IgnoreCLErrorHandler(prevResult, self)
  140.     int prevResult;
  141.     XR_MesaProc self;
  142. {
  143.     return 1;
  144. }
  145.  
  146. static struct XR_MesaProcRep XR_ignoreCLErrorHandler = {
  147.     (XR_UntypedProc)(XR_IgnoreCLErrorHandler),
  148.     (XR_Pointer)(NIL)
  149. };
  150.  
  151.  
  152. typedef struct XR_CLErrorHandlerDataRep {
  153.     XR_CLCallEnv clehd_clce;
  154.     int clehd_argc;
  155.     char **clehd_argv;
  156. } * XR_CLErrorHandlerData;
  157.  
  158.  
  159. static int
  160. XR_CmdCLErrorHandler(prevResult, self)
  161.     int prevResult;
  162.     XR_MesaProc self;
  163. {
  164.     XR_CLErrorHandlerData clehd = (XR_CLErrorHandlerData)(self->mp_x);
  165.  
  166. XR_ConsoleMsg("CmdCLErrorHandler pr %d\n", prevResult);
  167.     return 1;
  168. }
  169.  
  170.  
  171. /* command-file indirection */
  172.  
  173. typedef struct XR_PrePostProcDataRep {
  174.     bool pppd_echoing;
  175.     bool pppd_abortOnError;
  176.     XR_Ticks pppd_whenStarted;
  177. } * XR_PrePostProcData;
  178.  
  179.  
  180. static
  181. XR_CLPROC(XR_CLProc_preprocDefault)
  182. {
  183.     XR_PrePostProcData pppd = (XR_PrePostProcData)(clce->clce_clientData);
  184.     int i;
  185.  
  186.     if( !pppd->pppd_echoing ) {
  187.         /* if not echoing, might want to log the commands ... */
  188.         for( i = 0; i < argc; i++ ) {
  189.             XR_CLLogMsg "%s ", argv[i]);
  190.         }
  191.         XR_CLLogMsg "\n");
  192.     }
  193.     pppd->pppd_whenStarted = XR_TicksSinceBoot();
  194.     return 0;
  195. }
  196.  
  197. static struct XR_MesaProcRep XR_preprocDefault = {
  198.     (XR_UntypedProc)(XR_CLProc_preprocDefault),
  199.     (XR_Pointer)(NIL)
  200. };
  201.  
  202.  
  203. static
  204. XR_CLPROC(XR_CLProc_postprocDefault)
  205. {
  206.     XR_PrePostProcData pppd = (XR_PrePostProcData)(clce->clce_clientData);
  207.     XR_Ticks deltaTicks;
  208.     int ans = 1;
  209.  
  210.     if( prevResult <= 0 ) {
  211.         XR_CLErrorMsg "%s: failed", argv[0]);
  212.         if( prevResult == 0 ) {
  213.             XR_CLErrorMsg " (command not found)");
  214.         }
  215.         if( pppd->pppd_abortOnError ) {
  216.             XR_CLErrorMsg" ... aborting\n");
  217.             ans = (-1);
  218.         } else {
  219.             XR_CLErrorMsg " ... continuing\n");
  220.         }
  221.     }
  222.     deltaTicks = XR_TicksSinceBoot() - pppd->pppd_whenStarted + 1;
  223.     XR_CLStatsMsg "Elapsed time %d msec\n", XR_TicksToMsec(deltaTicks));
  224.     XR_CLLogMsg "\n");
  225.     return ans;
  226. }
  227.  
  228. static struct XR_MesaProcRep XR_postprocDefault = {
  229.     (XR_UntypedProc)(XR_CLProc_postprocDefault),
  230.     (XR_Pointer)(NIL)
  231. };
  232.  
  233.  
  234.  
  235. static
  236. XR_CLPROC(XR_CLProc_atSign)
  237. {
  238.     XR_Fildes fd, pfd;
  239.     bool isStdin;
  240.     XR_CLHandle h;
  241.     struct XR_PrePostProcDataRep pppdNew;
  242.     struct XR_CLCallEnvRep clceNew;
  243.     int nestedVerbosity;
  244.     int applyAns;
  245.  
  246.     if( argc > 2 ) {
  247.         XR_CLErrorMsg "%s args: [command_file_name]\n", argv[0]);
  248.         return (-1);
  249.     }
  250.     if( argc > 1 ) {
  251.         isStdin = FALSE;
  252.         pfd = XR_nullFildes;
  253.         fd = XR_Open(argv[1], O_RDONLY, 0);
  254.         if( fd == XR_nullFildes ) {
  255.             XR_CLErrorMsg "%s: cannot open %s\n", argv[0], argv[1]);
  256.             return (-1);
  257.         }
  258.         (void) XR_SetGetBlocking(fd, XR_UIO_BLOCKING_SOME_DATA); /* default */
  259.         XR_CLLogMsg "Reading commands from file %s:\n\n", argv[1]);
  260.     } else {
  261.         isStdin = TRUE;
  262.         pfd = XR_MSG_STDOUT;
  263.         fd = XR_MSG_STDIN;
  264.     }
  265.  
  266.     h = XR_CLCreateHandleFromFile(fd, pfd);
  267.     if( h != NIL ) {
  268.  
  269.         pppdNew.pppd_echoing = (isStdin);
  270.         pppdNew.pppd_abortOnError = (!isStdin);
  271.  
  272.         clceNew.clce_h = h;
  273.         clceNew.clce_pH = clce->clce_pH;
  274.         clceNew.clce_msgSink = clce->clce_msgSink;
  275.         nestedVerbosity = *(clce->clce_msgVerbosityP);
  276.         clceNew.clce_msgVerbosityP = &nestedVerbosity;
  277.         clceNew.clce_handlerProc = NIL;
  278.         clceNew.clce_clientData = (XR_Pointer)(&(pppdNew));
  279.  
  280.         (void) XR_SetTopLevelCLCallEnv(&clceNew);
  281.         applyAns = XR_CLApply(
  282.                 &clceNew, &XR_preprocDefault, &XR_postprocDefault );
  283.         (void) XR_SetTopLevelCLCallEnv(clce);
  284.  
  285.         (void) XR_CLDestroyHandle(h);
  286.  
  287.     } else {
  288.  
  289.         XR_CLErrorMsg "%s: out of memory\n", argv[0]);
  290.         if( !isStdin ) (void) XR_Close(fd);
  291.         return (-1);
  292.  
  293.     }
  294.  
  295.     if( !isStdin ) {
  296.         (void) XR_Close(fd);
  297.         XR_CLLogMsg "\nDone reading commands from file %s\n", argv[1]);
  298.     }
  299.     return applyAns;
  300. }
  301.  
  302.  
  303. /*
  304.  * Function call
  305.  */
  306.  
  307. #define XR_CLLookupFunc(name, externOnly, recentOnly) \
  308.     ((XR_UntypedProc)(XR_ILLookupFunc((name), (externOnly), (recentOnly)))
  309.  
  310.  
  311. #define XR_IL_CALL_FUNC_MAX_ARGC    8
  312.  
  313. int
  314. XR_CLCallProc(proc, argc, argv, resultP)
  315.     XR_Pointer (*proc)();
  316.     int argc;
  317.     XR_Pointer *argv;
  318.     XR_Pointer *resultP;
  319. {
  320.     XR_Pointer resultBuf;
  321. #   define CALL (*resultP) = (*proc)
  322.  
  323.     if( proc == NIL ) return (-2);
  324.     if( resultP == NIL ) resultP = (&resultBuf);
  325.  
  326.     switch(argc) {
  327.         case 0: CALL();
  328.             break;
  329.         case 1: CALL(argv[0]);
  330.             break;
  331.         case 2: CALL(argv[0], argv[1]);
  332.             break;
  333.         case 3: CALL(argv[0], argv[1], argv[2]);
  334.             break;
  335.         case 4: CALL(argv[0], argv[1], argv[2], argv[3]);
  336.             break;
  337.         case 5: CALL(argv[0], argv[1], argv[2], argv[3],
  338.                     argv[4]);
  339.             break;
  340.         case 6: CALL(argv[0], argv[1], argv[2], argv[3],
  341.                     argv[4], argv[5]);
  342.             break;
  343.         case 7: CALL(argv[0], argv[1], argv[2], argv[3],
  344.                     argv[4], argv[5], argv[6]);
  345.             break;
  346.         case 8: CALL(argv[0], argv[1], argv[2], argv[3],
  347.                     argv[4], argv[5], argv[6], argv[7]);
  348.             break;
  349. #       if (XR_IL_CALL_FUNC_MAX_ARGC != 8)
  350.             --> fix me! <--
  351. #           endif
  352.         default:
  353.             return (-1);
  354.     }
  355.     return 0;
  356. }
  357. #undef CALL
  358.  
  359.  
  360. static
  361. XR_CLPROC(XR_CLProc_call_procs)
  362. {
  363.     bool externOnly;
  364.     bool recentOnly;
  365.     XR_ILError ile = NIL;
  366.     XR_UntypedProc proc;
  367.     int i, ans;
  368.     char *myRealName = ((char *)(self->mp_x));
  369.  
  370.     if( strcmp(myRealName, "call_procs") == 0 ) {
  371.         externOnly = FALSE;  recentOnly = TRUE;
  372.     } else {
  373.         externOnly = FALSE;  recentOnly = FALSE;
  374.     }
  375.     for( i = 1; i < argc; i++ ) {
  376.         ile = XR_LockIncrementalLoadState(TRUE);
  377.         if( ile != NIL ) {
  378.             XR_CLErrorMsg "%s: can't lock loadstate\n", argv[0]);
  379.             return (-1);
  380.         }
  381.         proc = (XR_UntypedProc)
  382.                 XR_ILLookupProc( argv[i], externOnly, recentOnly);
  383.         (void) XR_UnlockIncrementalLoadState();
  384.         if( proc == NIL ) {
  385.             XR_CLErrorMsg "%s: can't find procedure %s\n", argv[0], argv[i]);
  386.             return (-1);
  387.         }
  388.         XR_CLLogMsg "calling ");
  389.         if( externOnly ) { XR_CLLogMsg "extern proc "); }
  390.         XR_CLLogMsg "%s() ... ", argv[i]);
  391.         ans = XR_CLCallProc( proc, argc-2, argv+2, NIL );
  392.         if( ans < 0 ) {
  393.             XR_CLErrorMsg "%s: call %s failed\n", argv[0], argv[i]);
  394.             return (-1);
  395.         }
  396.         XR_CLLogMsg "ok\n");
  397.     }
  398.     return 1;
  399. }
  400.  
  401.  
  402. static
  403. XR_CLPROC(XR_CLProc_call)
  404. {
  405.     bool externOnly;
  406.     bool recentOnly;
  407.     XR_ILError ile = NIL;
  408.     XR_UntypedProc proc;
  409.     int i, ans;
  410.     char *myRealName = ((char *)(self->mp_x));
  411.  
  412.     if( argc < 2 ) {
  413.         XR_CLErrorMsg "%s args: function_name [arg ...]\n", argv[0]);
  414.         return(-1);
  415.     }
  416.     if( strcmp(myRealName, "call") == 0 ) {
  417.         externOnly = FALSE;  recentOnly = TRUE;
  418.     } else {
  419.         externOnly = FALSE;  recentOnly = FALSE;
  420.     }
  421.     ile = XR_LockIncrementalLoadState(TRUE);
  422.     if( ile != NIL ) {
  423.         XR_CLErrorMsg "%s: can't lock loadstate\n", argv[0]);
  424.         return (-1);
  425.     }
  426.     proc = (XR_UntypedProc) XR_ILLookupProc(argv[1], externOnly, recentOnly);
  427.     (void) XR_UnlockIncrementalLoadState();
  428.     if( proc == NIL ) {
  429.         XR_CLErrorMsg "%s: can't find procedure %s\n", argv[0], argv[1]);
  430.         return (-1);
  431.     }
  432.     XR_CLLogMsg "calling ");
  433.     if( externOnly ) { XR_CLLogMsg "extern proc "); }
  434.     XR_CLLogMsg "%s (", argv[1]);
  435.     for( i = 2; i < argc; i++ ) {
  436.         XR_CLLogMsg "%s", argv[i]);
  437.         if( (i+1) < argc ) { XR_CLLogMsg ", "); }
  438.     }
  439.     XR_CLLogMsg ") ... ");
  440.     ans = XR_CLCallProc( proc, argc-2, argv+2, NIL );
  441.     if( ans < 0 ) {
  442.         XR_CLErrorMsg "%s: call %s failed\n", argv[0], argv[1]);
  443.         return (-1);
  444.     }
  445.     XR_CLLogMsg "ok\n");
  446.     return 1;
  447. }
  448.  
  449.  
  450. /*
  451.  * Load / UnixLoad
  452.  */
  453.  
  454. XR_UntypedProc
  455. XR_CLProcFromPrefixAndFileName(pfx, fn, externOnly, recentOnly)
  456.     char *pfx;
  457.     char *fn;
  458.     bool externOnly;
  459.     bool recentOnly;
  460. {
  461.     int pfxLen, sfxLen;
  462.     char *buf;
  463.     char *pl, *pr;
  464.     XR_UntypedProc proc = NIL;
  465.  
  466.     if( pfx == NIL ) pfx = "";
  467.     pfxLen = strlen(pfx);
  468.     if( fn != NIL ) {
  469.         if( (pl = strrchr(fn, '/')) != NIL ) { pl++; } else { pl = fn; }
  470.         sfxLen = strlen(pl);
  471.         if( (pr = strchr(pl, '.')) != NIL ) sfxLen = (pr - pl);
  472.         if( (buf = (char *) XR_malloc(pfxLen+1+sfxLen+1)) == NIL ) return;
  473.         (void)strcpy(buf, pfx);
  474.         (void)strcpy(buf+pfxLen, "_");
  475.         (void)strncpy(buf+pfxLen+1, pl, sfxLen);
  476.         buf[pfxLen+1+sfxLen] = 0;
  477.         proc = (XR_UntypedProc) XR_ILLookupProc( buf, externOnly, recentOnly );
  478.     }
  479.     if( (proc == NIL) && (pfxLen > 0) && (externOnly || recentOnly) ) {
  480.         proc = (XR_UntypedProc) XR_ILLookupProc( pfx, externOnly, recentOnly );
  481.     }
  482.     return proc;
  483. }
  484.  
  485.  
  486. typedef struct XR_PrintUndefinedDataRep {
  487.     bool pud_firstEntry;
  488.     XR_CLCallEnv pud_clce;
  489. } *XR_PrintUndefinedData;
  490.  
  491.  
  492. static bool
  493. XR_PrintUndefinedSymbol(se, clientData)
  494.     XR_ILSymEntry se;
  495.     XR_Pointer clientData;
  496. {
  497. #   define pud ((XR_PrintUndefinedData)(clientData))
  498.     XR_CLCallEnv clce = pud->pud_clce;
  499.  
  500.     if( pud->pud_firstEntry ) {
  501.         XR_CLErrorMsg "Undefined:\n");
  502.         pud->pud_firstEntry = FALSE;
  503.     }
  504.     XR_CLErrorMsg "    %s", se->ilse_name);
  505.     if( se->ilse_ilfe != NIL ) {
  506.         XR_CLErrorMsg
  507.                 " (referenced from %s)", se->ilse_ilfe->ilfe_fName);
  508.     }
  509.     XR_CLErrorMsg "\n");
  510.     return TRUE;
  511. }
  512. #undef pud
  513.  
  514. static void
  515. XR_LoadCommandPatchSizeProc(ilfe, bytes)
  516.     XR_ILFileEntry ilfe;
  517.     unsigned bytes;
  518. {
  519.     ilfe->ilfe_pBytes = bytes;
  520. }
  521.  
  522. static
  523. XR_CLPROC(XR_CLProc_load)
  524. {
  525.     XR_ILError ile = NIL;
  526.     XR_ILSymEntry ilse;
  527.     int i;
  528.     void (*patchSizeProc)() = NIL;
  529.     long int patchBytes = 0;
  530.  
  531.     ile = XR_LockIncrementalLoadState(TRUE);
  532.     if( ile != NIL ) {
  533.         XR_CLErrorMsg "%s: error %d: %s\n",
  534.             argv[0], ile->ile_code, ile->ile_msg);
  535.         return (-1);
  536.     }
  537.     for( i = 1; i < argc; i++ ) {
  538.         if( (argv[i][0] == '-') && (argv[i][1] == 'p') ) {
  539.             patchBytes = atoi(&(argv[i][2]));
  540.             if( patchBytes > 0 ) {
  541.                 patchSizeProc = XR_LoadCommandPatchSizeProc;
  542.             } else {
  543.                 if( patchBytes < 0 )
  544.                     XR_CLLogMsg "bad flag %s ignored ... ", argv[i]);
  545.                 patchSizeProc = NIL;
  546.                 patchBytes = 0;
  547.             }
  548.             continue;
  549.         }
  550.         XR_CLLogMsg "loading %s ... ", argv[i]);
  551.         ile = XR_ILLoadFile(
  552.             /*fName*/            argv[i],
  553.             /*fOffset*/            0,
  554.             /*fMagic*/            0,
  555.             /*refProc*/            NIL,
  556.             /*refClientData*/        NIL,
  557.             /*defProc*/            NIL,
  558.             /*defClientData*/        NIL,
  559.             /*commonProc*/        NIL,
  560.             /*commonClientData*/    NIL,
  561.             /*patchSizeProc*/        patchSizeProc,
  562.             /*patchSizeClientData*/    patchBytes
  563.         );
  564.         if( ile != NIL ) {
  565.             XR_CLLogMsg "error %d: %s\n", ile->ile_code, ile->ile_msg);
  566.             break;
  567.         }
  568.         XR_CLLogMsg "ok\n");
  569.     }
  570.     if( ile == NIL ) {
  571.         ile = XR_CommitIncrementalLoad();
  572.     }
  573.     if( ile != NIL ) {
  574.         struct XR_PrintUndefinedDataRep pud;
  575.         pud.pud_firstEntry = TRUE;
  576.         pud.pud_clce = clce;
  577.         XR_ILEnumerateUndefinedSyms(
  578.                 XR_PrintUndefinedSymbol,
  579.                 ((XR_Pointer)(&pud)) );
  580.         (void) XR_AbortIncrementalLoad(NIL);
  581.         (void) XR_UnlockIncrementalLoadState();
  582.         XR_CLErrorMsg "%s: error %d: %s\n",
  583.             argv[0], ile->ile_code, ile->ile_msg);
  584.         if( i < argc ) XR_CLErrorMsg "\tfile: %s\n", argv[i]);
  585.         return (-1);
  586.     } else {
  587.         (void) XR_UnlockIncrementalLoadState();
  588.         return 1;
  589.     }
  590. }
  591.  
  592.  
  593. static
  594. XR_CLPROC(XR_CLProc_unixload)
  595. {
  596.     XR_ILError ile = NIL;
  597.     XR_Pointer (*proc)();
  598.     int ans, loadAns;
  599.  
  600.     if( argc == 2 ) goto Try;
  601.     if( (argc == 3) && (argv[1][0] == '-') && (argv[1][1] == 'p') ) goto Try;
  602.     XR_CLErrorMsg "%s args: file_name\n", argv[0]);
  603.     return(-1);
  604.  
  605. Try:
  606.  
  607.     loadAns = XR_CLCallIndirect(clce,
  608.             "load_files", argc, argv);
  609.     if( loadAns <= 0 ) {
  610.         /* already printed:
  611.             XR_CLErrorMsg "%s: failed to load %s\n", argv[0], argv[1]); */
  612.         return (-1);
  613.     }
  614.     ile = XR_LockIncrementalLoadState(TRUE);
  615.     if( ile != NIL ) {
  616.         XR_CLErrorMsg "%s: error %d: %s\n",
  617.             argv[0], ile->ile_code, ile->ile_msg);
  618.         return (-1);
  619.     }
  620.     proc = XR_CLProcFromPrefixAndFileName(
  621.             "_XR_run", argv[1], FALSE, TRUE );
  622.     (void) XR_UnlockIncrementalLoadState();
  623.     if( proc != NIL ) {
  624.         XR_CLLogMsg "calling run proc ... ");
  625.         ans = XR_CLCallProc( proc, 0, NIL, NIL );
  626.         if( ans < 0 ) XR_Panic("XR_CLProc_unixload 0");
  627.         XR_CLLogMsg "ok\n");
  628.     } else {
  629.         XR_CLWarningMsg "%s: warning: can't find run proc for %s\n",
  630.                 argv[0], argv[1] );
  631.     }
  632.     return 1;
  633. }
  634.  
  635.  
  636. /*
  637.  * Verbosity control
  638.  */
  639.  
  640. static
  641. XR_CLPROC(XR_CLProc_msgs)
  642. {
  643.     char *myRealName = ((char *)(self->mp_x));
  644.     int oldVerbosity, newVerbosity;
  645.  
  646.     switch(argc) {
  647.         case 1:
  648.             if( strcmp(myRealName, "verbose") == 0 ) {
  649.                 newVerbosity = XR_VERBOSITY_VERBOSE;
  650.             } else if( strcmp(myRealName, "quiet") == 0 ) {
  651.                 newVerbosity = XR_VERBOSITY_QUIET;
  652.             } else {
  653.                 newVerbosity = XR_VERBOSITY_NORMAL;
  654.             }
  655.             break;
  656.         case 2:
  657.             if( strcmpcase(argv[1], "verbose") == 0 ) {
  658.                 newVerbosity = XR_VERBOSITY_VERBOSE;
  659.             } else if( strcmpcase(argv[1], "quiet") == 0 ) {
  660.                 newVerbosity = XR_VERBOSITY_QUIET;
  661.             } else if( strcmpcase(argv[1], "normal") == 0 ) {
  662.                 newVerbosity = XR_VERBOSITY_NORMAL;
  663.             } else if( (newVerbosity = atoi(argv[1])) >= 0 ) {
  664.                 ;
  665.             } else {
  666.                 goto Bad;
  667.             }
  668.             break;
  669.         default:
  670.             goto Bad;
  671.     }
  672.     oldVerbosity = *(clce->clce_msgVerbosityP);
  673.     if( myRealName[0] == 'g' ) {
  674.         XR_verbosity = newVerbosity;
  675.         XR_CLLogMsg "global ");
  676.     }
  677.     *(clce->clce_msgVerbosityP) = newVerbosity;
  678.     XR_CLLogMsg "verbosity set to %d (was %d)\n",
  679.             newVerbosity, oldVerbosity);
  680.     return 1;
  681.   Bad:
  682.     XR_CLErrorMsg "%s arg: [verbosity_level]\n", argv[0]);
  683.     return (-1);
  684. }
  685.  
  686.  
  687.  
  688.  
  689.  
  690. /*
  691.  * Start the world
  692.  */
  693.  
  694. static struct XR_MLRep XR_packageInstallationLock;
  695. static bool XR_packageInstalled = FALSE;
  696.  
  697. static
  698. XR_CLPROC(XR_CLProc_install_and_run_package)
  699. {
  700.     bool notMyProblem;
  701.     extern void XR_InstallAndRunPackage();
  702.     extern char XR_packageVersion[];
  703.  
  704.     XR_MonitorEntry(&XR_packageInstallationLock);
  705.     notMyProblem = XR_packageInstalled;
  706.     XR_packageInstalled = TRUE;
  707.     XR_MonitorExit(&XR_packageInstallationLock);
  708.  
  709.     if( notMyProblem ) {
  710.         XR_CLWarningMsg "%s: (do not use)\n", argv[0]);
  711.         return 1;
  712.     } else {
  713.         XR_CLLogMsg "initializing pkg version %s ...\n", XR_packageVersion);
  714.         XR_InstallAndRunPackage();
  715.         XR_CLLogMsg " ... package initialized\n");
  716.         return 1;
  717.     }
  718. }
  719.  
  720.  
  721. /*
  722.  * quit the world ...
  723.  */
  724.  
  725. static
  726. XR_CLPROC(XR_CLProc_quit)
  727. {
  728.     XR_CLNormalMsg "good-bye\n");
  729.     XR_ExitWorld( (argc > 1) ? atoi(argv[1]) : 0 );
  730. }
  731.  
  732.  
  733.  
  734. /*
  735.  * The amazing copywrite message ... 
  736.  */
  737. char *(XR_copyrightMessageLines[]) = {
  738.  
  739. "Copyright (c) 1988, 1989, 1990 Xerox Corporation. All rights reserved.",
  740. "Use and copying of this software and preparation of derivative works based",
  741. "upon this software are permitted. Any distribution of this software or",
  742. "derivative works must comply with all applicable United States export",
  743. "control laws. This software is made available AS IS, and Xerox Corporation",
  744. "makes no warranty about the software, its performance or its conformity to",
  745. "any specification. Any person obtaining a copy of this software is requested",
  746. "to send their name and post office or electronic mail address to",
  747. "PCRCoordinator.pa@xerox.com, or",
  748. "\tPCR Coordinator",
  749. "\tXerox PARC",
  750. "\t3333 Coyote Hill Rd.",
  751. "\tPalo Alto, CA 94304",
  752. NIL
  753. };
  754.  
  755. static
  756. XR_CLPROC(XR_CLProc_copyright)
  757. {
  758.     char **p;
  759.     extern char XR_threadsVersion[];
  760.  
  761.     XR_CLMsg "\nXerox Portable Common Runtime (PCR)\n");
  762.     XR_CLMsg "Version %s\n\n", XR_threadsVersion);
  763.     for( p = XR_copyrightMessageLines; *p != NIL; p++ ) {
  764.         XR_CLMsg "%s\n", *p );
  765.     }
  766.     XR_CLMsg "\n");
  767.     return 1;
  768. }
  769.  
  770.  
  771. /*
  772.  * Help facility
  773.  */
  774.  
  775. static bool
  776. XR_PrintOneHelpMessage(r, self)
  777.     XR_CLRegistration r;
  778.     XR_MesaProc self;
  779. {
  780.     XR_CLCallEnv clce = (XR_CLCallEnv)(self->mp_x);
  781.     char *key;
  782.     char *helpMsg;
  783.  
  784.     if( r == NIL ) XR_Panic("XR_PrintOneHelpMessage");
  785.     XR_CLGetRegistrationDetails(r, &key, NIL, &helpMsg, NIL, NIL);
  786.     if( helpMsg != NIL ) { XR_CLMsg "  %s %s\n", key, helpMsg); }
  787.     return TRUE;
  788. }
  789.  
  790. static
  791. XR_CLPROC(XR_CLProc_help)
  792. {
  793.     XR_MesaProc printProc;
  794.     XR_CLRegistration r;
  795.     int i;
  796.  
  797.     printProc = XR_MakeMesaProc(
  798.             ((XR_UntypedProc)(XR_PrintOneHelpMessage)),
  799.             ((XR_Pointer)(clce)) );
  800.     if( argc <= 1 ) {
  801.         XR_CLMsg "Registered commands:\n\n");
  802.         XR_CLEnumerateRegistrations( clce->clce_pH, printProc );
  803.         XR_CLMsg "\n");
  804.         return 1;
  805.     }
  806.     for( i = 1; i < argc; i++ ) {
  807.         r = XR_CLGetRegistrationWithKey( clce->clce_pH, argv[i] );
  808.         if( r != NIL ) {
  809.             (void) XR_PrintOneHelpMessage(r, printProc);
  810.         } else {
  811.             XR_CLMsg "  %s not registered\n", argv[i]);
  812.         }
  813.     }
  814.     return 1;
  815. }
  816.  
  817.  
  818. /*
  819.  * generic proc to set file name string
  820.  */
  821.  
  822. static int
  823. XR_SetFileName(fn, buf, bufLen, bufp)
  824.     char *fn;
  825.     char *buf;
  826.     int bufLen;
  827.     char **bufp;
  828. {
  829.     int fnLen;
  830.     char *cwd;
  831.     int cwdLen;
  832.     extern char *getenv();
  833.  
  834.     if( fn == NIL ) {
  835.         *bufp = NIL;
  836.         return 0;
  837.     }
  838.     fnLen = strlen(fn);
  839.     if( fn[0] == '/' ) {
  840.         if( fnLen >= bufLen ) {
  841.             return (-1);
  842.         }
  843.         strcpy( buf, fn );
  844.         *bufp = buf;
  845.         return 0;
  846.     }
  847.     cwd = getenv("PWD");
  848.     if( cwd == NIL ) {
  849.         return (-1);
  850.     }
  851.     cwdLen = strlen(cwd);
  852.     if( (cwdLen + fnLen + 1) >= bufLen ) {
  853.         return (-1);
  854.     }
  855.     strcpy( buf, cwd );
  856.     buf[cwdLen] = '/';
  857.     strcpy( buf+cwdLen+1, fn );
  858.     *bufp = buf;
  859.     return 0;
  860. }
  861.  
  862.  
  863. /*
  864.  * pcr file name -- for internalizing symbols, set during initialization
  865.  */
  866.  
  867. static char XR_pcrFileNameBuf[256] = "./pcr"; /* hah! */
  868. static char *XR_pcrFileName = NIL;
  869.  
  870. int
  871. XR_SetPCRFileName(fn)
  872.     char *fn;
  873. {
  874.     return XR_SetFileName(fn, XR_pcrFileNameBuf,
  875.             (sizeof XR_pcrFileNameBuf), &XR_pcrFileName );
  876. }
  877.  
  878. char *
  879. XR_GetPCRFileName()
  880. {
  881.     return XR_pcrFileName;
  882. }
  883.  
  884.  
  885. /*
  886.  * temp directory -- may be set during initialization
  887.  */
  888.  
  889. static char XR_tmpDirectoryBuf[256] = XR_DEFAULT_TMP_DIRECTORY;
  890. static char *XR_tmpDirectory = XR_tmpDirectoryBuf;
  891.  
  892. int
  893. XR_SetTmpDirectory(d)
  894.     char *d;
  895. {
  896.     return XR_SetFileName(d, XR_tmpDirectoryBuf,
  897.             (sizeof XR_tmpDirectoryBuf), &XR_tmpDirectory );
  898. }
  899.  
  900. char *
  901. XR_GetTmpDirectory()
  902. {
  903.     return XR_tmpDirectory;
  904. }
  905.  
  906. char *
  907. XR_get_loader_directory() /* OBSOLESCENT */
  908. {
  909.     return XR_GetTmpDirectory();
  910. }
  911.  
  912.  
  913. /*
  914.  * dbxscript file name -- set during initialization
  915.  */
  916.  
  917. static char XR_nameOfDBXScriptBuf[256] = XR_DEFAULT_DBX_SCRIPT_NAME;
  918. static char *XR_nameOfDBXScript = XR_nameOfDBXScriptBuf;
  919.  
  920. int
  921. XR_SetDBXScriptName(n)
  922.     char *n;
  923. {
  924.     return XR_SetFileName(n, XR_nameOfDBXScriptBuf,
  925.             (sizeof XR_nameOfDBXScriptBuf), &XR_nameOfDBXScript );
  926. }
  927.  
  928.  
  929. char *
  930. XR_GetDBXScriptName()
  931. {
  932.     return XR_nameOfDBXScript;
  933. }
  934.  
  935.  
  936.     
  937. /*
  938.  * Comand registration
  939.  */
  940.  
  941. static char *(XR_clProcDescriptions[]) = {
  942.  
  943.     (char *)XR_CLProc_help, NIL,
  944.         "[cmdname ...] -- print help messages",
  945.         "help", "?", NIL,
  946.  
  947.     (char *)XR_CLProc_quit, NIL,
  948.         " -- quit pcr",
  949.         "quit", "exit", NIL,
  950.  
  951.     (char *)XR_CLProc_msgs, "quiet",
  952.         "['quiet'|'normal'|'verbose'|level] -- set quiet mode",
  953.         "quiet", NIL,
  954.     (char *)XR_CLProc_msgs, "verbose",
  955.         "['verbose'|'normal'|'quiet'|level] -- set verbose mode",
  956.         "verbose", NIL,
  957.     (char *)XR_CLProc_msgs, "msgs",
  958.         "['normal'|'quiet'|'verbose'|level] -- set msg mode",
  959.         "msgs", NIL,
  960.  
  961.     (char *)XR_CLProc_msgs, "global_msgs",
  962.         "['normal'|'quiet'|'verbose'|level] -- set msg mode",
  963.         "global_msgs", NIL,
  964.  
  965.     (char *)XR_CLProc_load, "load_files",
  966.         "[-ppatchsize] filename ... -- load object files",
  967.         "load", "load_files", "nolibload_files", NIL,
  968.  
  969.     (char *)XR_CLProc_unixload, NIL,
  970.         "[-ppatchsize] filename -- load_files filename ; call _XR_run_<name> or _XR_run",
  971.         "unixload", "uload", NIL,
  972.  
  973.     (char *)XR_CLProc_call, "call",
  974.         "procname [arg ...] -- call proc in current file",
  975.         "call", NIL,
  976.     (char *)XR_CLProc_call, "callall",
  977.         "procname [arg ...] -- call proc",
  978.         "callall", NIL,
  979.     (char *)XR_CLProc_call_procs, "call_procs",
  980.         "procname ... -- call procs in current file, no args",
  981.         "call_procs", NIL,
  982.     (char *)XR_CLProc_call_procs, "callall_procs",
  983.         "procname ... -- call procs, no args",
  984.         "callall_procs", NIL,
  985.  
  986.     (char *)XR_CLProc_atSign, NIL,
  987.         "[filename] -- include commands from named file or stdin",
  988.         "@", "include", NIL,
  989.  
  990.     (char *)XR_CLProc_copyright, NIL,
  991.         " -- print copyright message",
  992.         "copyright", NIL,
  993.  
  994.     (char *)XR_CLProc_install_and_run_package, NIL,
  995.         " -- (do not use)",
  996.         "install_and_run_package", NIL,
  997.  
  998.     NIL
  999. };
  1000.  
  1001.  
  1002. void
  1003. XR_SetupCommandLoop()
  1004. {
  1005.     int registerAns;
  1006.  
  1007.     XR_globalCLProcsHandle = XR_CLCreateProcsHandle();
  1008.     if( XR_globalCLProcsHandle == NIL ) {
  1009.         XR_Panic("SetupCommandLoop 0");
  1010.     }
  1011.     registerAns = XR_CLUnsafeRegisterProcs(
  1012.             XR_globalCLProcsHandle, XR_clProcDescriptions );
  1013.     if( registerAns < 0 ) {
  1014.         XR_Panic("SetupCommandLoop 1");
  1015.     }
  1016. }
  1017.  
  1018.  
  1019. static void
  1020. XR_CreateDBXScript(scriptName)
  1021.     char *scriptName;
  1022. {
  1023.     char infoFileName[256];
  1024.     int pid;
  1025.     XR_Fildes fd;
  1026.  
  1027.     XR_ILGetInfoFileName(infoFileName);
  1028.     pid = XR_GetPID();
  1029.     fd = XR_Open(scriptName, (O_CREAT|O_WRONLY|O_TRUNC), 0777);
  1030.     if( fd == XR_nullFildes ) {
  1031.         XR_WarningVMsg "Cannot create %s\n", scriptName);
  1032.         return;
  1033.     }
  1034.     XR_FPrintF(fd,
  1035.             "# PCR debugging initialization file to be sourced by XrDBX.\n");
  1036.     XR_FPrintF(fd,
  1037.             "set core = %d\n", pid);
  1038.     XR_FPrintF(fd,
  1039.             "set model = %s\n", infoFileName);
  1040.     (void) XR_Close(fd);
  1041.     XR_NormalVMsg "%s installed.\n", scriptName);
  1042. }
  1043.  
  1044.  
  1045. static void
  1046. XR_MakeGlobalCLHandle()
  1047. {
  1048.     int pkgArgc;
  1049.     char **pkgArgv;
  1050.     int pos0, lim0, pos1, lim1, posCL, limCL;
  1051.     XR_CLHandle h;
  1052.     int ans;
  1053.  
  1054.     XR_GetPackageDefaultArgs(&pkgArgc, &pkgArgv);
  1055.     for( pos0 = 0; pos0 < pkgArgc; pos0++ ) {
  1056.         if( strcmp(pkgArgv[pos0], "--") == 0 ) break;
  1057.     }
  1058.     pos0 += 1;
  1059.     for( lim0 = pos0; lim0 < pkgArgc; lim0++ ) {
  1060.         if( strcmp(pkgArgv[lim0], "--") == 0 ) break;
  1061.     }
  1062.     pos1 = lim0 + 1;
  1063.     lim1 = pkgArgc;
  1064.  
  1065.     for( posCL = 1; posCL < XR_argc; posCL++ ) {
  1066.         if( strcmp(XR_argv[posCL], "--") == 0 ) break;
  1067.     }
  1068.     posCL += 1; 
  1069.     limCL = XR_argc;
  1070.  
  1071.     h = XR_CLCreateHandleFromArgs(0, NIL, NIL);
  1072.     if( h == NIL ) XR_Panic("MakeGlobalCLHandle 0");
  1073.     if( pos1 < lim1 ) {
  1074.         ans = XR_CLPrependArgsToHandle(
  1075.                 h, (lim1 - pos1), (pkgArgv + pos1) );
  1076.         if( ans < 0 ) XR_Panic("MakeGlobalCLHandle 1");
  1077.     }
  1078.     if( posCL < limCL ) {
  1079.         ans = XR_CLPrependArgsToHandle(
  1080.                 h, (limCL - posCL), (XR_argv + posCL) );
  1081.         if( ans < 0 ) XR_Panic("MakeGlobalCLHandle 2");
  1082.     }
  1083.     if( pos0 < lim0 ) {
  1084.         ans = XR_CLPrependArgsToHandle(
  1085.                 h, (lim0 - pos0), (pkgArgv + pos0) );
  1086.         if( ans < 0 ) XR_Panic("MakeGlobalCLHandle 3");
  1087.     }
  1088.     XR_globalCLHandle = h;
  1089. }
  1090.  
  1091.  
  1092.  
  1093. static int
  1094. XR_ProcessCommandLineArguments()
  1095. {
  1096.     struct XR_PrePostProcDataRep pppd;
  1097.     struct XR_CLCallEnvRep clce;
  1098.     XR_CLCallEnv clceOld;
  1099.     int result;
  1100.  
  1101.     pppd.pppd_echoing = FALSE;
  1102.     pppd.pppd_abortOnError = TRUE;
  1103.     clce.clce_h = XR_globalCLHandle;
  1104.     clce.clce_pH = XR_globalCLProcsHandle;
  1105.     clce.clce_msgSink = XR_stdOutCLMsgSink;
  1106.     clce.clce_msgVerbosityP = &XR_verbosity;
  1107.     clce.clce_handlerProc = NIL;
  1108.     clce.clce_clientData = (XR_Pointer)(&pppd);
  1109.     clceOld = XR_SetTopLevelCLCallEnv(&clce);
  1110.     result = XR_CLApply( &clce, &XR_preprocDefault, &XR_postprocDefault );
  1111.     (void) XR_SetTopLevelCLCallEnv(clceOld);
  1112.     return result;
  1113. }
  1114.  
  1115.  
  1116. void
  1117. XR_StartMainXR ()
  1118. {
  1119.     char *tmpStr;
  1120.  
  1121.     if( (tmpStr = XR_GetPCRFileName()) != NIL )
  1122.         (void) init_dyload(tmpStr, FALSE, FALSE);
  1123.     if( (tmpStr = XR_GetDBXScriptName()) != NIL )
  1124.         XR_CreateDBXScript(tmpStr);
  1125.     XR_MakeGlobalCLHandle();
  1126.     (void)XR_ProcessCommandLineArguments();
  1127.     XR_WarningVMsg "PCR returns from XR_Start.  Terminating.\n");
  1128.     XR_ExitWorld(0);
  1129. }
  1130.  
  1131.